home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug189 / pr.c < prev    next >
Text File  |  1985-08-21  |  8KB  |  320 lines

  1. /*
  2.  *   pr.c:  detabbing file printer -
  3.  *
  4.  *        usage:  pr [options] [file1 file2 ...]
  5.  *        options:
  6.  *               -b#     begin printing with page #
  7.  *               -c#     print # copies
  8.  *               -d      delete file after printing
  9.  *               -e#     end printing with page #
  10.  *               -hs     use title s instead of filename (NULL = no header)
  11.  *               -l      print with line numbers
  12.  *               -m#     print with a left margin of # spaces
  13.  *               -n#     print # lines per page (header xtra)
  14.  *               -s#     print with spacing of # lines
  15.  *               -t#     set tabs every # spaces (default 4)
  16.  *               -w#     define page width (default 256)
  17.  *
  18.  *       Other than tabs, all control characters are suppressed.
  19.  *
  20.  *       Adapted from Software Tools by Chuck Allison - May 1985
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <ctype.h>
  25. #include <time.h>
  26. #include <types.h>  /* MWC only */
  27.  
  28. #define inrange(x) (start <= x && x <= stop)
  29. #define getnum(x) x = atoi(s+1); goto next_arg
  30.  
  31. #define MAXINT 32767
  32. #define MAXLINE 256
  33. #define yes 1
  34. #define no 0
  35.  
  36. /* ..set default parameters.. */
  37. int number = no,
  38.     delete = no,
  39.     print_lines_pp = 55,
  40.     text_lines_pp = 55,
  41.     margin = 3,
  42.     spacing = 1,
  43.     tabspace = 4,
  44.     width = 256,
  45.     headers = yes,
  46.     copies = 1,
  47.     start = 1,
  48.     stop = MAXINT;
  49.  
  50. static tabstops[MAXLINE];
  51. time_t time_val;
  52. static char timestr[25], title[36] = "";
  53. extern char *trim_fspec();
  54.  
  55. main(argc,argv)
  56. int argc;
  57. char *argv[];
  58. {
  59.     int hour;
  60.     register char *s;
  61.  
  62.     /* ..process switches.. */
  63.     while (--argc && (**++argv == '-'|| **argv == '/'))
  64.     {
  65.         for (s = *argv+1; *s; ++s)
  66.             switch(tolower(*s))
  67.             {
  68.                 case 'b':
  69.                     getnum(start);
  70.                 case 'd':
  71.                     delete = yes;
  72.                     break;
  73.                 case 'e':
  74.                     getnum(stop);
  75.                 case 'h':
  76.                     if (s[1])
  77.                     {
  78.                         strcpy(title,++s);
  79.                         goto next_arg;
  80.                     }
  81.                     else
  82.                     {
  83.                         headers = no;
  84.                         break;
  85.                     }
  86.                 case 'l':
  87.                     number = yes;
  88.                     break;
  89.                 case 'm':
  90.                     getnum(margin);
  91.                 case 'n':
  92.                     getnum(print_lines_pp);
  93.                 case 's':
  94.                     getnum(spacing);
  95.                 case 't':
  96.                     getnum(tabspace);
  97.                 case 'c':
  98.                     getnum(copies);
  99.                 case 'w':
  100.                     getnum(width);
  101.                 default :
  102.                     fprintf(stderr,"---> ERROR: bad switch: -%c\n",*s);
  103.                     exit(1);
  104.             }
  105.         next_arg: /* ..cycle on outer for().. */ ;
  106.     }
  107.  
  108.     /* ..initialize tab settings.. */
  109.     settabs();
  110.  
  111.     /* ..validate line spacing.. */
  112.     if (spacing <= 0 || print_lines_pp <= spacing)
  113.     {
  114.         fprintf(stderr,"---> ERROR: Spacing invalid\n");
  115.         exit(1);
  116.     }
  117.     text_lines_pp = 1 + (print_lines_pp - 1) / spacing;
  118.     
  119.     /* ..get date and time.. */
  120.     time(&time_val);
  121.     strcpy(timestr,ctime(&time_val));
  122.     timestr[24] = '\0';   /* ..zap newline.. */
  123.     /* ..Replace seconds with am/pm.. */
  124.     timestr[16] = ' ';
  125.     hour = 10*(timestr[11] - '0') + (timestr[12] - '0');
  126.     if (hour >= 12)
  127.     {
  128.         timestr[17] = 'p';
  129.         if (hour > 12)
  130.         {
  131.             hour -= 12;
  132.             timestr[12] = hour%10 + '0';
  133.             timestr[11] = (hour /= 10) ? hour + '0' : ' ';
  134.         }
  135.    }
  136.     else
  137.     {
  138.         timestr[17] = 'a';
  139.         if (hour == 0)
  140.         {
  141.             timestr[11] = '1';
  142.             timestr[12] = '2';
  143.         }
  144.         else if (timestr[11] == '0')
  145.             timestr[11] = ' ';
  146.     }
  147.     timestr[18] = 'm';
  148.  
  149.     /* ..process files.. */
  150.     if (argc == 0)
  151.         process(title);
  152.     else
  153.     {
  154.         /* ..print each file.. */
  155.         for (; *argv; ++argv)
  156.             if (freopen(*argv,"r",stdin) != NULL)
  157.             {
  158.                 process((strlen(title) == 0) ? *argv : title);
  159.                 if (delete)
  160.                     if (unlink(*argv) != 0)
  161.                         fprintf(stderr,"---> WARNING: can't delete %s\n",*argv);
  162.                     else
  163.                         fprintf(stderr,"---> %s deleted.\n",*argv);
  164.             }
  165.             else
  166.                 fprintf(stderr,"---> ERROR: can't process %s\n",*argv);
  167.     }
  168. }
  169.  
  170. process(f)
  171. char *f;
  172. {
  173.     register i;
  174.  
  175.     for (i = 0; i < copies; ++i)
  176.     {
  177.          rewind(stdin);
  178.          pr(f);
  179.     }
  180. }
  181.  
  182. pr(name)
  183. char *name;
  184. {
  185.     register lineno, i;
  186.     int pageno, offset;
  187.     char line[MAXLINE];
  188.     extern char *rindex();
  189.     
  190.     offset = 0;
  191.     pageno = 1;
  192.     lineno = 1;
  193.     
  194.     fprintf(stderr,"---> printing %s...\n",name);
  195.  
  196.     /* ..trim a long file name.. */
  197.     trim_fspec(name,name,30);
  198.  
  199.     /* ..output initial header.. */
  200.     if (inrange(pageno))
  201.         if (headers)
  202.             header(name,pageno);
  203.         else
  204.             printf("\n\n\n\n");
  205.  
  206.     while (fgets(line,MAXLINE-1,stdin) != NULL)
  207.     {
  208.         /* ..check page range.. */
  209.         if (pageno > stop)
  210.             return;
  211.             
  212.         if (lineno == 0)
  213.         {
  214.             lineno = 1;
  215.             if (inrange(pageno))
  216.                 if (headers)
  217.                     header(name,pageno);
  218.                 else
  219.                     printf("\n\n\n\n");
  220.         }
  221.  
  222.         if (pageno > stop)
  223.             return;
  224.  
  225.         /* ..print line, with number, if requested.. */
  226.         if (inrange(pageno))
  227.         {
  228.             do_margin();
  229.             if (number)
  230.                 printf("%5d  ",offset+lineno);
  231.             else
  232.                 printf("  ");
  233.             detab(line);
  234.             if (lineno+1 <= text_lines_pp)
  235.                 for (i = 1; i < spacing; ++i)
  236.                     putchar('\n');
  237.         }
  238.  
  239.         /* ..check for page break.. */
  240.         if (++lineno > text_lines_pp)
  241.         {
  242.             if (inrange(pageno))
  243.                 putchar('\f');
  244.             offset += text_lines_pp;
  245.             ++pageno;
  246.             lineno = 0;
  247.         }
  248.     }
  249.  
  250.     /* ..form-feed after last partial page.. */
  251.     if (inrange(pageno))
  252.         if (lineno > 0)
  253.             putchar('\f');
  254. }
  255.  
  256. header(file,page)
  257. char *file;
  258. int page;
  259. {
  260.     register i;
  261.  
  262.     putchar('\n');
  263.     do_margin();
  264.     for (i = 0; i < 75; ++i)
  265.         putchar('-');
  266.     putchar('\n');
  267.     do_margin();
  268.     printf("%-36.36s%-30.30sPage%5d",file,timestr,page);
  269.     putchar('\n');
  270.     do_margin();
  271.     for (i = 0; i < 75; ++i)
  272.         putchar('-');
  273.     printf("\n\n\n");
  274. }
  275.  
  276. detab(line)
  277. char *line;
  278. {
  279.     register i, col;
  280.  
  281.     col = 0;
  282.  
  283.     /* ..note: line[] has a terminating '\n' per fgets().. */
  284.     for (i = 0; col < width-margin-(number?7:2) && i < strlen(line); ++i)
  285.         if (line[i] == '\t')
  286.             do
  287.             {
  288.                 /* ..tab.. */
  289.                 putchar(' ');
  290.                 ++col;
  291.             } while (!tabstops[col]);
  292.         else if (line[i] == '\n' || isprint(line[i]))
  293.         {
  294.             putchar(line[i]);
  295.             ++col;
  296.         }
  297.     if (i < strlen(line))
  298.         putchar('\n');
  299. }
  300.  
  301. settabs()
  302. {
  303.     register i;
  304.  
  305.     tabstops[0] = 0;
  306.     for (i = 1; i < MAXLINE; ++i)
  307.         tabstops[i] = (i % tabspace == 0);
  308. }
  309.  
  310. do_margin()
  311. {
  312.     register i;
  313.     
  314.     for (i = 0; i < margin; ++i)
  315.         putchar(' ');
  316. }
  317.           putchar(' ');
  318.                 ++col;
  319.             } while (!tabstops[col]);
  320.         else if (line[